package com.junxonline.plat.service.charge.impl;

import com.junxonline.common.exception.CommonBizException;
import com.junxonline.common.util.CommonUtils;
import com.junxonline.common.util.FileUtils;
import com.junxonline.plat.dao.model.Category;
import com.junxonline.plat.dao.model.Charge;
import com.junxonline.plat.dao.model.HouseFloorPlan;
import com.junxonline.plat.dao.model.Household;
import com.junxonline.plat.dao.repository.CategoryRepository;
import com.junxonline.plat.dao.repository.ChargeRepository;
import com.junxonline.plat.dao.repository.HouseholdRepository;
import com.junxonline.plat.dao.vo.*;
import com.junxonline.plat.service.charge.ChargeService;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.criteria.*;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Service
@Transactional
public class ChargeServiceImpl implements ChargeService {

    private Logger logger = LogManager.getLogger();

    @Autowired
    private ChargeRepository chargeRepository;

    @Autowired
    private CategoryRepository categoryRepository;

    @Autowired
    private HouseholdRepository householdRepository;

    /**
     * 获取收费数据
     *
     * @param vo
     * @return
     */
    @Override
    public ChargeVO getCharge(QueryChargeVO vo) {

        Charge charge = chargeRepository.findByChargeId(vo.getChargeId());

        ChargeVO chargeVO = new ChargeVO();
        chargeVO.setChargeId(charge.getChargeId());
        chargeVO.setChargeYearMonth(charge.getChargeYearMonth());
        chargeVO.setChargeMoney(charge.getChargeMoney());

        Category category = charge.getCategory();
        if (CommonUtils.isNotEmpty(category)) {
            chargeVO.setCategoryId(category.getCategoryId());
            chargeVO.setCategoryName(category.getCategoryName());
            chargeVO.setCategoryUnit(category.getCategoryUnit());
            chargeVO.setCategoryPrice(category.getCategoryPrice());
        }

        Household household = charge.getHousehold();
        if (CommonUtils.isNotEmpty(household)) {
            chargeVO.setHouseholdId(household.getHouseholdId());
            chargeVO.setHouseholdName(household.getHouseholdName());
            chargeVO.setHouseholdNo(household.getHouseholdNo());
        }

        return chargeVO;
    }

    /**
     * 筛选查询收费
     *
     * @param pageVO
     * @param vo
     * @return
     */
    @Override
    public PageVO queryCharge(PageVO pageVO, QueryChargeVO vo) {

        PageRequest pageRequest = PageRequest.of(pageVO.getPage() - 1, pageVO.getLimit(), new Sort(Sort.Direction.ASC, "chargeId"));

        Page<Charge> page = chargeRepository.findAll(new Specification<Charge>() {
            @Override
            public Predicate toPredicate(Root<Charge> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {

                List<Predicate> params = new ArrayList<>();
                String householdNo = vo.getHouseholdNo();
                String householdName = vo.getHouseholdName();
                String chargeYearMonth = vo.getChargeYearMonth();
                Long categoryId = vo.getCategoryId();

                Join householdMap = root.join("household", JoinType.LEFT);

                Join categoryMap = root.join("category", JoinType.LEFT);

                params.add(criteriaBuilder.equal(householdMap.get("isHousehold"), 1));

                if (CommonUtils.isNotEmpty(householdNo)) {
                    params.add(criteriaBuilder.like(householdMap.get("householdNo"), "%" + householdNo + "%"));
                }

                if (CommonUtils.isNotEmpty(householdName)) {
                    params.add(criteriaBuilder.like(householdMap.get("householdName"), "%" + householdName + "%"));
                }

                if (CommonUtils.isNotEmpty(categoryId)) {
                    params.add(criteriaBuilder.equal(categoryMap.get("categoryId"), categoryId));
                }

                if (CommonUtils.isNotEmpty(chargeYearMonth)) {
                    params.add(criteriaBuilder.like(root.get("chargeYearMonth").as(String.class), "%" + chargeYearMonth + "%"));
                }

                return criteriaBuilder.and(params.toArray(new Predicate[params.size()]));
            }
        }, pageRequest);

        List<ChargeVO> chargeVOs = new ArrayList<>();
        List<Charge> charges = page.getContent();

        for (Charge charge : charges) {

            ChargeVO chargeVO = new ChargeVO();
            chargeVO.setChargeYearMonth(charge.getChargeYearMonth());
            chargeVO.setChargeId(charge.getChargeId());
            chargeVO.setChargeMoney(charge.getChargeMoney());

            Category category = charge.getCategory();
            if (CommonUtils.isNotEmpty(category)) {
                chargeVO.setCategoryId(category.getCategoryId());
                chargeVO.setCategoryName(category.getCategoryName());
                chargeVO.setCategoryUnit(category.getCategoryUnit());
                chargeVO.setCategoryPrice(category.getCategoryPrice());
            }

            Household household = charge.getHousehold();
            if (CommonUtils.isNotEmpty(household)) {
                chargeVO.setHouseholdId(household.getHouseholdId());
                chargeVO.setHouseholdName(household.getHouseholdName());
                chargeVO.setHouseholdNo(household.getHouseholdNo());
            }

            chargeVOs.add(chargeVO);
        }

        pageVO.setTotal(page.getTotalElements());
        pageVO.setData(chargeVOs);

        return pageVO;

    }

    /**
     * 添加收费
     *
     * @param vo
     * @return
     */
    @Override
    public boolean addCharge(ChargeVO vo) {

        Charge charge = new Charge();
        charge.setChargeYearMonth(vo.getChargeYearMonth());
        charge.setChargeMoney(vo.getChargeMoney());

        Category category = categoryRepository.findByCategoryId(vo.getCategoryId());

        if (CommonUtils.isEmpty(category)) {
            throw CommonBizException.SYSTEM_ERROR;
        }

        charge.setCategory(category);

        Household household = householdRepository.findByHouseholdId(vo.getHouseholdId());

        if (CommonUtils.isEmpty(household)) {
            throw CommonBizException.SYSTEM_ERROR;
        }

        charge.setHousehold(household);

        chargeRepository.save(charge);

        return true;
    }

    /**
     * 修改收费
     *
     * @param vo
     * @return
     */
    @Override
    public boolean editCharge(ChargeVO vo) {

        Charge charge = chargeRepository.findByChargeId(vo.getChargeId());

        charge.setChargeYearMonth(vo.getChargeYearMonth());
        charge.setChargeMoney(vo.getChargeMoney());

        // 处理收费类别
        if (CommonUtils.isNotEmpty(vo.getCategoryId())) {

            Category category = categoryRepository.findByCategoryId(vo.getCategoryId());

            if (CommonUtils.isNotEmpty(category)) {
                charge.setCategory(category);
            }
        }

        if (CommonUtils.isNotEmpty(vo.getHouseholdId())) {

            Household household = householdRepository.findByHouseholdId(vo.getHouseholdId());

            if (CommonUtils.isNotEmpty(household)) {
                charge.setHousehold(household);
            }
        }

        chargeRepository.save(charge);

        return true;
    }

    /**
     * 删除收费
     *
     * @param chargeIds
     * @return
     */
    @Override
    public boolean delCharge(Long[] chargeIds) {

        List<Charge> charges = chargeRepository.findByChargeIdIn(chargeIds);

        for (Charge charge : charges) {
            // 删除收费
            chargeRepository.delete(charge);
        }

        return true;
    }

    /**
     * 获取收费类别数据
     *
     * @return
     */
    @Override
    public List<CategoryVO> getCategory() {

        List<CategoryVO> categoryVOList = new ArrayList<>();
        List<Category> categories = categoryRepository.findAll();

        for (Category category : categories) {

            CategoryVO categoryVO = new CategoryVO();
            categoryVO.setCategoryId(category.getCategoryId());
            categoryVO.setCategoryName(category.getCategoryName());

            categoryVOList.add(categoryVO);
        }

        return categoryVOList;
    }


    /**
     * 获取住户数据
     *
     * @param vo
     * @return
     */
    @Override
    public List<HouseholdVO> getHousehold(QueryHouseholdVO vo) {

        List<HouseholdVO> householdVOList = new ArrayList<>();
        List<Household> households = householdRepository.findByHouseholdNameLikeAndIsHousehold(vo.getHouseholdName(), 1);

        for (Household household : households) {

            HouseholdVO householdVO = new HouseholdVO();
            householdVO.setHouseholdId(household.getHouseholdId());
            householdVO.setHouseholdName(household.getHouseholdName());
            householdVO.setHouseholdNo(household.getHouseholdNo());
            householdVOList.add(householdVO);
        }

        return householdVOList;
    }

    /**
     * 查询需要交费并且手机号有填写的住户
     */
    @Override
    public List<HouseholdVO> findByNeedChargeHousehold() {

        List<HouseholdVO> householdVOList = new ArrayList<>();

        List<Map<String, Object>> households = chargeRepository.findByNeedChargeHousehold();

        logger.info("开始检查需要缴费的住户...");

        for (Map<String, Object> map : households) {

            BigInteger householdId = (BigInteger) map.get("household_id");
            String householdName = (String) map.get("household_name");
            String householdNo = (String) map.get("household_no");
            String householdPhone = (String) map.get("household_phone");
            Double chargeMoney = (Double) map.get("charge_money");

            // 先检查手机号是否填写
            if (CommonUtils.isEmpty(householdPhone)) {
                logger.info("跳过住户：[" + householdNo + "]" + householdName + " 原因：手机号未填写");
                break;
            }
            else {
                HouseholdVO householdVO = new HouseholdVO();
                householdVO.setHouseholdId(householdId.longValue());
                householdVO.setHouseholdName(householdName);
                householdVO.setHouseholdNo(householdNo);
                householdVO.setHouseholdPhone(householdPhone);
                householdVO.setChargeMoney(chargeMoney);
                householdVOList.add(householdVO);
                logger.info("住户：[" + householdNo + "]" + householdName + " 加入发送短信队列");
            }

        }

        return householdVOList;

    }
}
